package com.zxy.supplier_system.server.configuration

import jakarta.servlet.http.HttpServletRequest
import org.springframework.core.annotation.AnnotationUtils
import org.springframework.lang.Nullable
import org.springframework.web.servlet.mvc.condition.RequestCondition
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
import java.lang.reflect.Method
import java.util.*

@Retention(AnnotationRetention.RUNTIME)
@Target(
    AnnotationTarget.CLASS,
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER
)
annotation class ClientVersion(val value: String)
const val DEFAULT_VERSION = "1.0.0"

class ClientVersionHandlerMapping : RequestMappingHandlerMapping() {
    override fun getCustomTypeCondition(handlerType: Class<*>): RequestCondition<*> {
        return createCondition(
            AnnotationUtils.findAnnotation(
                handlerType,
                ClientVersion::class.java
            )
        )
    }

    override fun getCustomMethodCondition(method: Method): RequestCondition<*> {
        method.isAccessible = true
        val clientVersion = AnnotationUtils.findAnnotation(
            method,
            ClientVersion::class.java
        )
        return createCondition(clientVersion)
    }

    private fun createCondition(@Nullable clientVersion: ClientVersion?): ClientVersionRequestCondition {
        val version = Optional.ofNullable(clientVersion).map { obj: ClientVersion -> obj.value }.orElse(
            DEFAULT_VERSION
        )
        return ClientVersionRequestCondition(version)
    }
}


class ClientVersionRequestCondition(
    private val version: String
) : RequestCondition<ClientVersionRequestCondition> {

    override fun combine(other: ClientVersionRequestCondition): ClientVersionRequestCondition {
        return if (other.version >= version) other else this
    }

    override fun getMatchingCondition(request: HttpServletRequest): ClientVersionRequestCondition? {
        val clientSideVersionFromRequest = getClientSideVersionFromRequest(request)
        return if (clientSideVersionFromRequest >= version) {
            // 接口指定的版本小于等于客户端的版本
            this
        } else null
    }

    override fun compareTo(other: ClientVersionRequestCondition, request: HttpServletRequest): Int {
        return compareVersion(other.version, version)
    }

    private fun getClientSideVersionFromRequest(request: HttpServletRequest): String {
        return request.getHeader("client-version") ?: DEFAULT_VERSION
    }

    private fun compareVersion(version1: String, version2: String): Int {
        val version1Fragments = version1.split(".")
        val version2Fragments = version2.split(".")
        for (i in 0..2) {
            val f1 = version1Fragments[i]
            val f2 = version2Fragments[i]
            if (f1 > f2) {
                return 1
            }else if (f1<f2){
                return -1
            }
        }
        return 0
    }
}
